//! 数字生成器模块

use once_cell::sync::Lazy;
use rand::Rng;
use rand::seq::SliceRandom;
use std::fs;

/// 从文件加载手机号码前缀
static PHONE_PREFIXES_CN: Lazy<Vec<String>> =
    Lazy::new(|| load_data_from_file("data/generators/number/phone_prefixes_cn.txt"));

/// 从文件加载地区代码
static AREA_CODES_CN: Lazy<Vec<String>> =
    Lazy::new(|| load_data_from_file("data/generators/number/area_codes_cn.txt"));

/// 从文件加载数据的辅助函数
fn load_data_from_file(file_path: &str) -> Vec<String> {
    match fs::read_to_string(file_path) {
        Ok(content) => content
            .lines()
            .map(|line| line.trim().to_string())
            .filter(|line| !line.is_empty())
            .collect(),
        Err(_) => {
            // 如果文件不存在，返回默认数据
            match file_path {
                "data/generators/number/phone_prefixes_cn.txt" => vec![
                    "130".to_string(),
                    "131".to_string(),
                    "132".to_string(),
                    "133".to_string(),
                    "134".to_string(),
                    "135".to_string(),
                ],
                "data/generators/number/area_codes_cn.txt" => vec![
                    "110000".to_string(),
                    "120000".to_string(),
                    "130000".to_string(),
                    "140000".to_string(),
                    "150000".to_string(),
                    "210000".to_string(),
                ],
                _ => vec!["Default".to_string()],
            }
        }
    }
}

/// 生成指定范围的整数
pub fn integer(min: i64, max: i64) -> i64 {
    let mut rng = rand::thread_rng();
    rng.gen_range(min..=max)
}

/// 生成指定范围的浮点数
pub fn float(min: f64, max: f64) -> f64 {
    let mut rng = rand::thread_rng();
    rng.gen_range(min..=max)
}

/// 生成指定精度的浮点数
pub fn float_with_precision(min: f64, max: f64, precision: usize) -> f64 {
    let value = float(min, max);
    let multiplier = 10_f64.powi(precision as i32);
    (value * multiplier).round() / multiplier
}

/// 生成正整数
pub fn positive_integer(max: i64) -> i64 {
    integer(1, max)
}

/// 生成负整数
pub fn negative_integer(min: i64) -> i64 {
    integer(min, -1)
}

/// 生成百分比（0-100）
pub fn percentage() -> f64 {
    float(0.0, 100.0)
}

/// 生成概率值（0.0-1.0）
pub fn probability() -> f64 {
    float(0.0, 1.0)
}

/// 生成货币金额
pub fn currency(min: f64, max: f64) -> f64 {
    float_with_precision(min, max, 2)
}

/// 生成年龄
pub fn age() -> u8 {
    let mut rng = rand::thread_rng();
    rng.gen_range(1..=120)
}

/// 生成成人年龄（18-80）
pub fn adult_age() -> u8 {
    let mut rng = rand::thread_rng();
    rng.gen_range(18..=80)
}

/// 生成儿童年龄（1-17）
pub fn child_age() -> u8 {
    let mut rng = rand::thread_rng();
    rng.gen_range(1..=17)
}

/// 生成分数（0-100）
pub fn score() -> u8 {
    let mut rng = rand::thread_rng();
    rng.gen_range(0..=100)
}

/// 生成及格分数（60-100）
pub fn passing_score() -> u8 {
    let mut rng = rand::thread_rng();
    rng.gen_range(60..=100)
}

/// 生成不及格分数（0-59）
pub fn failing_score() -> u8 {
    let mut rng = rand::thread_rng();
    rng.gen_range(0..=59)
}

/// 生成温度（摄氏度）
pub fn temperature_celsius() -> f64 {
    float_with_precision(-50.0, 50.0, 1)
}

/// 生成温度（华氏度）
pub fn temperature_fahrenheit() -> f64 {
    float_with_precision(-58.0, 122.0, 1)
}

/// 生成指定范围内的随机整数
pub fn random_int(min: i32, max: i32) -> i32 {
    let mut rng = rand::thread_rng();
    rng.gen_range(min..=max)
}

/// 生成指定范围内的随机浮点数
pub fn random_float(min: f64, max: f64) -> f64 {
    let mut rng = rand::thread_rng();
    rng.gen_range(min..=max)
}

/// 生成体重（公斤）
pub fn weight_kg() -> f64 {
    float_with_precision(40.0, 150.0, 1)
}

/// 生成BMI指数
pub fn bmi() -> f64 {
    float_with_precision(15.0, 40.0, 1)
}

/// 生成银行卡号（16位）
pub fn credit_card_number() -> String {
    let mut rng = rand::thread_rng();
    (0..16)
        .map(|_| rng.gen_range(0..=9).to_string())
        .collect::<Vec<_>>()
        .join("")
}

/// 生成手机号码（中国）
pub fn phone_number_cn() -> String {
    let mut rng = rand::thread_rng();
    use rand::seq::SliceRandom;

    let prefix = PHONE_PREFIXES_CN.choose(&mut rng).unwrap();
    let suffix: String = (0..8).map(|_| rng.gen_range(0..=9).to_string()).collect();

    format!("{}{}", prefix, suffix)
}

/// 生成青少年年龄（13-19岁）
pub fn teenager_age() -> u8 {
    let mut rng = rand::thread_rng();
    rng.gen_range(13..=19)
}

/// 生成老年人年龄（60-100岁）
pub fn senior_age() -> u8 {
    let mut rng = rand::thread_rng();
    rng.gen_range(60..=100)
}

/// 生成价格（0.01-9999.99）
pub fn price() -> f64 {
    let mut rng = rand::thread_rng();
    rng.gen_range(0.01..=9999.99)
}

/// 生成工资（20000-1000000）
pub fn salary() -> u32 {
    let mut rng = rand::thread_rng();
    rng.gen_range(20000..=1000000)
}

/// 生成电话号码（通用）
pub fn phone_number() -> String {
    phone_number_cn()
}

/// 生成信用卡号（别名）
pub fn credit_card() -> String {
    credit_card_number()
}

/// 生成银行卡号（中国）
pub fn bank_card_cn() -> String {
    let mut rng = rand::thread_rng();
    let prefixes = ["6225", "6227", "6228", "6229", "6230"]; // 常见银行卡前缀
    let prefix = prefixes.choose(&mut rng).unwrap();
    let remaining_digits: String = (0..12)
        .map(|_| rng.gen_range(0..=9).to_string())
        .collect();
    format!("{}{}", prefix, remaining_digits)
}

/// 生成身份证号码（中国，18位）
pub fn id_card_cn() -> String {
    let mut rng = rand::thread_rng();
    use rand::seq::SliceRandom;

    // 地区代码（前6位）
    let area_code = AREA_CODES_CN.choose(&mut rng).unwrap();

    // 出生日期（8位）
    let year = rng.gen_range(1950..=2005);
    let month = rng.gen_range(1..=12);
    let day = rng.gen_range(1..=28);
    let birth_date = format!("{:04}{:02}{:02}", year, month, day);

    // 顺序码（3位）
    let sequence = format!("{:03}", rng.gen_range(1..=999));

    // 前17位
    let first_17 = format!("{}{}{}", area_code, birth_date, sequence);

    // 校验码（第18位）
    let check_digit = calculate_id_check_digit(&first_17);

    format!("{}{}", first_17, check_digit)
}

/// 计算身份证校验码
fn calculate_id_check_digit(first_17: &str) -> char {
    let weights = [7, 9, 10, 5, 8, 4, 2, 1, 6, 3, 7, 9, 10, 5, 8, 4, 2];
    let check_chars = ['1', '0', 'X', '9', '8', '7', '6', '5', '4', '3', '2'];

    let sum: usize = first_17
        .chars()
        .enumerate()
        .map(|(i, c)| c.to_digit(10).unwrap() as usize * weights[i])
        .sum();

    check_chars[sum % 11]
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn test_integer() {
        let num = integer(1, 10);
        assert!(num >= 1 && num <= 10);
    }

    #[test]
    fn test_float_with_precision() {
        let num = float_with_precision(1.0, 2.0, 2);
        let decimal_places = format!("{:.10}", num)
            .split('.')
            .nth(1)
            .unwrap()
            .trim_end_matches('0')
            .len();
        assert!(decimal_places <= 2);
    }

    #[test]
    fn test_adult_age() {
        let age = adult_age();
        assert!(age >= 18 && age <= 80);
    }

    #[test]
    fn test_phone_number_cn() {
        let phone = phone_number_cn();
        assert_eq!(phone.len(), 11);
        assert!(phone.starts_with('1'));
    }

    #[test]
    fn test_id_card_cn() {
        let id = id_card_cn();
        assert_eq!(id.len(), 18);
        assert!(id.chars().take(17).all(|c| c.is_ascii_digit()));
    }

    #[test]
    fn test_credit_card_number() {
        let card = credit_card_number();
        assert_eq!(card.len(), 16);
        assert!(card.chars().all(|c| c.is_ascii_digit()));
    }
}
